package com.lw.lwte.common.helper;

import cn.hutool.core.util.XmlUtil;
import com.beust.jcommander.internal.Maps;
import com.fasterxml.jackson.databind.ObjectMapper;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;

import java.io.*;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Map;
import java.util.Objects;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@SuppressWarnings("ALL")
@Slf4j
public class StringHelper extends StringUtils {

    private StringHelper() {}

    public static boolean isNull(String str) {
        return str == null || str.trim().length() == 0;
    }

    public static boolean isNullOrBlank(String str) {
        return isNull(str) || str.equals("") || str.equals("null");
    }

    public static boolean isNotNullAndBlank(String str) {
        return !isNullOrBlank(str);
    }

    public static boolean hasLength(String str) {
        return (str != null && str.length() > 0);
    }

    /**
     * 获取字符串的unicode编码
     *
     * @param str 字符串
     * @return unicode
     */
    public static String stringToUnicode(String str) {
        if (Objects.isNull(str)) {
            return null;
        }
        char[] chars = str.toCharArray();
        StringBuilder returnStr = new StringBuilder();
        for (char aChar : chars) {
            returnStr.append("\\u")
                    .append(Integer.toString(aChar, 16));
        }
        return returnStr.toString();
    }

    /**
     * Unicode转汉字字符串
     *
     * @param str unicode
     * @return 字符串
     */
    @SuppressWarnings("AlibabaAvoidPatternCompileInMethod")
    public static String unicodeToString(String str) {

        Pattern pattern = Pattern.compile("(\\\\u(\\p{XDigit}{4}))");
        Matcher matcher = pattern.matcher(str);
        char ch;
        while (matcher.find()) {
            //group 6728
            String group = matcher.group(2);
            //ch:'木' 26408
            ch = (char) Integer.parseInt(group, 16);
            //group1 \u6728
            String group1 = matcher.group(1);
            str = str.replace(group1, ch + "");
        }
        return str;
    }


    /**
     * Check whether the given CharSequence has actual text.
     * More specifically, returns {@code true} if the string not {@code null},
     * its length is greater than 0, and it contains at least one non-whitespace character.
     * <p><pre class="code">
     * StringUtils.hasText(null) = false
     * StringUtils.hasText("") = false
     * StringUtils.hasText(" ") = false
     * StringUtils.hasText("12345") = true
     * StringUtils.hasText(" 12345 ") = true
     * </pre>
     *
     * @param str the CharSequence to check (may be {@code null})
     * @return {@code true} if the CharSequence is not {@code null},
     * its length is greater than 0, and it does not contain whitespace only
     * @see Character#isWhitespace
     */
    public static boolean hasText(String str) {
        if (!hasLength(str)) {
            return false;
        }
        int strLen = str.length();
        for (int i = 0; i < strLen; i++) {
            if (!Character.isWhitespace(str.charAt(i))) {
                return true;
            }
        }
        return false;
    }

    /**
     * map转查询字符串
     * 如: a=1&b=2&c=3&...
     *
     * @param data
     */
    public static String map2QueryStr(Map<String, String> data) {
        if (CollectionHelper.isEmpty(data)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        data.forEach((k, v) ->
                sb.append(k)
                        .append("=")
                        .append(v)
                        .append("&")
        );
        if (sb.length() > 0) {
            sb.deleteCharAt(sb.length() - 1);
        }
        return sb.toString();
    }

    public static Map<String, String> queryStr2Map(String query) {
        Map<String, String> map = Maps.newHashMap();
        if (isBlank(query)) {
            return map;
        }
        String[] sections = query.split("&");
        for (String section : sections) {
            String[] pairs = section.split("=");
            if (pairs.length >= 2) {
                map.put(pairs[0], pairs[1]);
            } else {
                map.put(pairs[0], "");
            }
        }
        return map;
    }

    /**
     * map转cookie字符串
     * 如: a=1;b=2;c=3;...
     *
     * @param data
     */
    public static String map2CookieStr(Map<String, String> data) {
        if (CollectionHelper.isEmpty(data)) {
            return null;
        }
        StringBuilder sb = new StringBuilder();
        data.forEach((k, v) ->
                sb.append(k)
                        .append("=")
                        .append(v)
                        .append(";")
        );
        return sb.toString();
    }

    /**
     * 超出截断
     *
     * @param str       字符串
     * @param maxLength 最大长度
     */
    public static String substringIfOverflow(String str, int maxLength) {
        if (ValidateHelper.maxLength(maxLength, str)) {
            return str;
        }
        return str.substring(0, maxLength);
    }

    /**
     * str to map
     * k1:v1\n
     * k2:v2\n
     *
     * @param str
     */
    public static Map<String, String> str2Map(String str) {
        Map<String, String> map = Maps.newHashMap();
        if (Objects.isNull(str)) {
            return map;
        }
        String[] lines = str.split("\n");
        for (String line : lines) {
            if (StringHelper.isBlank(line)) {
                continue;
            }
            int index = line.indexOf(":");
            if (index < 0) {
                map.put(line.trim(), StringHelper.EMPTY);
                continue;
            }
            map.put(line.substring(0, index).trim(), line.substring(index + 1, line.length()).trim());
        }
        return map;
    }

    /**
     * URL编码
     *
     * @param text
     */
    public static String urlEncode(String text) {
        try {
            return URLEncoder.encode(text, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * URL解码
     *
     * @param text
     */
    public static String urlDecode(String text) {
        try {
            return URLDecoder.decode(text, "UTF-8");
        } catch (UnsupportedEncodingException e) {
            return null;
        }
    }

    /**
     * Returns an array with strings between start and end.
     *
     * @param value input
     * @param start start
     * @param end   end
     * @return Array containing different parts between start and end.
     */

    public static String[] between(final String value, final String start, final String end) {
        AssertHelper.notNull(value, "'value' should be not null.");
        AssertHelper.notNull(start, "'start' should be not null.");
        AssertHelper.notNull(end, "'end' should be not null.");
        String[] parts = value.split(end);
        return Arrays.stream(parts)
                .filter(subPart -> subPart.contains(start))
                .map(subPart -> subPart.substring(subPart.indexOf(start) + start.length()))
                .toArray(String[]::new);
    }

    /**
     * Returns first matched string between start and end.
     *
     * @param value input
     * @param start start
     * @param end   end
     */
    public static String firstBetween(final String value, final String start, final String end) {
        String[] betweenArray = between(value, start, end);
        if (CollectionHelper.isNotEmpty(betweenArray)) {
            return betweenArray[0];
        }
        return EMPTY;
    }

    /**
     * 首字母大写
     *
     * @param name
     * @return
     */
    public static String firstUpper(String name) {
        return name.substring(0, 1).toUpperCase() + name.substring(1);
    }

    /**
     * 首字母小写
     *
     * @param name
     * @return
     */
    public static String firstLower(String name) {
        return name.substring(0, 1).toLowerCase() + name.substring(1);
    }

    /**
     * 字符串优雅输出
     *
     * @param original
     * @return
     */
    public static String prettyFormat(String original) {
        if (original.contains("{") && original.contains("}")) {
            return jsonFormat(original);
        } else if (original.contains("<?xml")) {
            return xmlFormat(original);
        } else {
            return original;
        }
    }

    /**
     * json优雅输出
     *
     * @return
     */
    public static String jsonFormat(String original) {
        if (original.contains("{") && original.contains("}")) {
            ObjectMapper mapper = new ObjectMapper();
            Class valueType;
            try {
                Object obj = mapper.readValue(original, Object.class);
                return mapper.writerWithDefaultPrettyPrinter().writeValueAsString(obj);
            } catch (Exception e) {
                return original;
            }
        }

        return original;
    }

    /**
     * xml优雅输出
     *
     * @param original
     * @return
     */
    public static String xmlFormat(String original) {
        if (original.contains("<?xml")) {
            try {
                return XmlUtil.format(original);
            } catch (Exception e) {
                return original;
            }
        }

        return original;
    }

    /**
     * 获取换行符
     *
     * @return
     */
    public static String getLineSeparator() {
        return System.getProperty("line.separator");
    }

    /**
     * text转换为html
     * @param content
     * @return
     */
    public static String txtToHtml(String content) {
        StringBuilder sb = new StringBuilder(content.length());
        boolean lastWasBlankChar = false;
        int len = content.length();
        char c;

        for (int i = 0; i < len; i++) {
            c = content.charAt(i);
            if (c == ' ') {
                if (lastWasBlankChar) {
                    lastWasBlankChar = false;
                    sb.append("&nbsp;");
                } else {
                    lastWasBlankChar = true;
                    sb.append(' ');
                }
            } else {
                lastWasBlankChar = false;

                if (c == '"') {
                    sb.append("&quot;");
                } else if (c == '&') {
                    sb.append("&amp;");
                } else if (c == '<') {
                    sb.append("&lt;");
                } else if (c == '>') {
                    sb.append("&gt;");
                } else if (c == '\n') {
                    sb.append("<br/>");
                } else {
                    int ci = 0xffff & c;
                    if (ci < 160) {
                        sb.append(c);
                    } else {
                        sb.append("&#");
                        sb.append(new Integer(ci).toString());
                        sb.append(';');
                    }
                }
            }
        }

        return sb.toString();
    }
}
